﻿Imports PTIC_Util
Imports System.Data.OleDb
Imports System.Collections.ObjectModel
Imports System.Collections.Specialized

Public Class GeneriqueTypedParametre_EtatManuelDouble
    Inherits GeneriqueTypedParametre_EtatBase(Of Double)

    Public Sub New(ByVal parametre As GeneriqueTypedParametre(Of Double))
        MyBase.New(parametre)
    End Sub

    Public Overrides Sub MAJValeurs()

        If Parametre.ListeSegments.Count = 0 Then
            'La nouvelle valeur du paramètre n'est pas segmentée
            Dim TValeur As New DataTable
            TValeur.Columns.Add(Parametre.Nom, Parametre.Type)

            Dim NewRow As DataRow = TValeur.NewRow
            Dim moyAncienneValeur As Double = 0
            For Each rowAncienneValeur In Parametre.Valeurs.Rows
                moyAncienneValeur = moyAncienneValeur + rowAncienneValeur(Parametre.Nom)
            Next
            NewRow(Parametre.Nom) = moyAncienneValeur / Parametre.Valeurs.Rows.Count

            TValeur.Rows.Add(NewRow)
            Parametre.Valeurs = TValeur


        ElseIf Parametre.Valeurs.Columns.Count = 1 Then
            'L'ancienne valeur du paramètre n'est pas segmentée
            'Faire l'extraction puis réjouter une colonne toujours égale à l'ancienne valeur
            If Parametre.Requete.EtatCalcul_DataTable <> ValueEtatCalcul.A_JOUR Then
                Parametre.Requete.Calculer_DataTable()
                Dim TSegments As DataTable = Parametre.Requete.DataTableResultat
                TSegments.Columns.Add(Parametre.Nom, Parametre.Type)
                'Récupérer les éventuels segments de l'ancienne valeur et faire une jointure avec les nouvelles valeurs
                Dim ancienneValeur As Double = Parametre.Valeurs.Rows(0)(Parametre.Nom)
                For Each r As DataRow In TSegments.Rows
                    r(Parametre.Nom) = ancienneValeur
                Next
                Parametre.Valeurs = TSegments
            End If

        Else
            'Ancienne et nouvelle valeur du paramètre sont segmentées
            'Le paramètre est segmenté (la liste des segments contient au moins un élément
            If Parametre.Requete.EtatCalcul_DataTable <> ValueEtatCalcul.A_JOUR Then
                Parametre.Requete.Calculer_DataTable()
                If Parametre.Requete.EtatCalcul_DataTable = ValueEtatCalcul.A_JOUR Then
                    Dim TSegments As DataTable = Parametre.Requete.DataTableResultat
                    TSegments.Columns.Add(Parametre.Nom, Parametre.Type)
                    Dim TSegments_copy As DataTable = TSegments.Copy
                    combiner_OldNewValeurs(Parametre.Valeurs, TSegments_copy, Parametre.Nom)
                    Parametre.Valeurs = TSegments_copy
                End If
            End If
        End If
    End Sub
    Protected Sub combiner_OldNewValeurs(ByVal oldTable As DataTable, _
                                         ByVal newTable As DataTable, _
                                         ByVal nomParametre As String)

        'Ici, on suppose que chacune des deux table contient au moins un segment
        If Not oldTable Is Nothing And Not newTable Is Nothing Then

            'Liste des colonnes communes aux deux tables
            Dim NomsColonnesEnCommun As New List(Of String)
            For Each col As DataColumn In newTable.Columns
                If oldTable.Columns.Contains(col.ColumnName) Then
                    NomsColonnesEnCommun.Add(col.ColumnName)
                End If
            Next

            'Paramétrage des tableaux nécessaires à la relation (on supprime la colonne du paramètre + les CSR)
            Dim colOldTable(NomsColonnesEnCommun.Count - 2) As DataColumn
            Dim colNewTable(NomsColonnesEnCommun.Count - 2) As DataColumn
            Dim i As Integer = 0
            For Each nomSegment As String In NomsColonnesEnCommun
                If nomSegment <> nomParametre Then
                    colOldTable(i) = oldTable.Columns(nomSegment)
                    colNewTable(i) = newTable.Columns(nomSegment)
                    i = i + 1
                End If
            Next

            'Création de la nouvelle table contenant le résultat de la jointure
            Dim ds As DataSet
            ds = New DataSet
            oldTable.TableName = "OldTable"
            ds.Tables.Add(oldTable)
            ds.Tables.Add(newTable)
            ds.Relations.Add("relParametre", colNewTable, colOldTable, False)

            For Each newTableRow As DataRow In newTable.Rows
                'Récupérer les enfants de la ligne
                Dim ChildRows() As DataRow = newTableRow.GetChildRows("relParametre")

                If ChildRows.Count >= 2 Then
                    'La ligne contient plusieurs enfants
                    Dim ValueNewRow As Double = 0
                    For Each childRow As DataRow In ChildRows
                        'Faire une moyenne des différentes valeurs de la ligne
                        ValueNewRow = ValueNewRow + childRow(nomParametre)
                    Next
                    ValueNewRow = ValueNewRow / ChildRows.Count
                    newTableRow(nomParametre) = ValueNewRow

                Else
                    'La ligne ne contient qu'un seul enfant
                    newTableRow(nomParametre) = ChildRows(0)(nomParametre)

                End If
            Next
            ds.Relations.Clear()
            ds.Tables.Remove(oldTable)
            ds.Tables.Remove(newTable)
        End If

    End Sub

    Public Overrides Sub onListeSegmentsChanged(ByVal sender As Object, ByVal e As System.Collections.Specialized.NotifyCollectionChangedEventArgs)
        'MAJValeurs()
    End Sub

    Public Overrides Sub Deserialize(ByVal param As GeneriqueTypedParametre(Of Double))

        'Sauvegarde des caractéristiques actuelles du paramètre
        Dim AnciennesValeurs As DataTable = Me.Parametre.Valeurs.Copy
        Dim AnciensSegments As New Collection(Of String)
        For Each seg As String In Me.Parametre.ListeSegments
            AnciensSegments.Add(seg)
        Next

        'Alimentation des nouveaux segments du paramètre en fonction des valeurs sauvegardées
        Dim lSegments As ObservableCollection(Of String) = param.ListeSegments
        Me.Parametre.ListeSegments.Clear()
        For Each seg As String In lSegments
            Me.Parametre.ListeSegments.Add(seg)
        Next
        MAJValeurs()

        'Ici, les segments serializés sont renseignés dans le paramètre
        'Les valeurs sont alimentées à partir des anciennes valeurs
        'Maintenant, on va cherche à alimenter les valeurs sérializées dans le paramètre
        Dim valeurs_copy As DataTable = Me.Parametre.Valeurs.Copy
        Dim valeurs_Serializees_copy As DataTable = param.Valeurs.Copy

        Dim colValeurs(lSegments.Count - 1) As DataColumn
        Dim colValeursSerializees(lSegments.Count - 1) As DataColumn
        Dim i As Integer = 0
        For Each col As DataColumn In valeurs_Serializees_copy.Columns
            If valeurs_copy.Columns.Contains(col.ColumnName) And col.ColumnName <> Me.Parametre.Nom Then
                colValeurs(i) = valeurs_copy.Columns(col.ColumnName)
                colValeursSerializees(i) = col
                i = i + 1
            End If
        Next

        'Création de la nouvelle table contenant le résultat de la jointure
        Dim ds As DataSet
        valeurs_Serializees_copy.TableName = "ValeursSerializees"
        ds = New DataSet
        ds.Tables.Add(valeurs_copy)
        ds.Tables.Add(valeurs_Serializees_copy)
        ds.Relations.Add("relParametre", colValeurs, colValeursSerializees, False)

        'Parcours de la relation ligne à ligne
        Dim isOk As Boolean = True
        For Each newTableRow As DataRow In valeurs_copy.Rows
            'Récupérer les enfants de la ligne
            Dim ChildRows() As DataRow = newTableRow.GetChildRows("relParametre")

            If ChildRows.Count = 0 Then
                'La ligne contient plusieurs enfants
                'Pas de correspondance pour la ligne en cours
                isOk = False

            Else
                'La ligne ne contient qu'un seul enfant
                newTableRow(Me.Parametre.Nom) = ChildRows(0)(Me.Parametre.Nom)

            End If
        Next
        If Not isOk Then
            MsgBox("Le chargement du paramètre " & Me.Parametre.Nom & " n'a pas pu être effectuée entièrement car certaines valeurs du paramètre n'avaient pas de correspondance dans la sauvegarde.")
        End If
        ds.Relations.Clear()
        ds.Tables.Remove(valeurs_copy)
        ds.Tables.Remove(valeurs_Serializees_copy)
        Me.Parametre.Valeurs = valeurs_copy
    End Sub
End Class
